package blocks

import (
	"errors"
	"fmt"
	"github.com/FISCO-BCOS/go-sdk/client"
	"github.com/FISCO-BCOS/go-sdk/conf"
	"github.com/ethereum/go-ethereum/common"
	"log"
	"math/big"
)

// 调用区块链模块

const (
	ETHADDR = "0x93c2e62b37283c7311f7f071c204c7f9928bb9fe"
	CFGPATH = "/home/zf/data/code/go/src/xuanshang/gotaskFiscoBcos/blocks/config.toml"
)

var instance *Task
var Cli *client.Client

// TaskMsg 任务信息结构
type TaskMsg struct {
	TaskStatus uint8  `json:"task_status"`
	Bonus      int64  `json:"bonus"`
	Desc       string `json:"task_name"`
	Comment    string `json:"comment"`
	TaskID     string `json:"task_id"`
	Issuer     string `json:"issuer"`
	Worker     string `json:"task_user"`
}

// init 会自动触发运行，只要这个包被调用了，就会自动触发 init 函数的运行，此处用来初始化合约实例
func init() {
	// 链接到合约
	configs, err := conf.ParseConfigFile(CFGPATH)
	if err != nil {
		log.Panic("failed to ParseConfigFile", err)
	}
	config := &configs[0]
	Cli, err = client.Dial(config)
	if err != nil {
		log.Panic("failed to Dial", err)
	}
	task, err := NewTask(common.HexToAddress(ETHADDR), Cli)
	if err != nil {
		log.Panic("failed to NewTask", err)
	}
	// 创建身份
	instance = task
}

func Register(username, passwd string) error {
	if _, _, err := instance.Register(Cli.GetTransactOpts(), username, passwd); err != nil {
		fmt.Println("failed to Register", err)
		return errors.New(fmt.Sprintf("failed to Register:%v", err))
	}
	return nil
}

func Login(username, passwd string) (bool, error) {
	return instance.Login(Cli.GetCallOpts(), username, passwd)
}

func Issue(username, passwd, desc string, bonus int64) error {
	if _, _, err := instance.Issue(Cli.GetTransactOpts(), username, passwd, desc, big.NewInt(bonus)); err != nil {
		fmt.Println("failed to Issue", err)
		return errors.New(fmt.Sprintf("failed to Issue:%v", err))
	}
	return nil
}

// Update 修改任务状态，status: 1-接受任务，2-提交，3-确认，4-退回
func Update(username, passwd, comment string, status uint8, taskID int64) error {
	switch status {
	case 1:
		if _, _, err := instance.Take(Cli.GetTransactOpts(), username, passwd, big.NewInt(taskID)); err != nil {
			fmt.Println("failed to Take task1", err)
			return errors.New(fmt.Sprintf("failed to Take task1:%v", err))
		}
	case 2:
		if _, _, err := instance.Commit(Cli.GetTransactOpts(), username, passwd, big.NewInt(taskID)); err != nil {
			fmt.Println("failed to commit task2", err)
			return errors.New(fmt.Sprintf("failed to commit task2:%v", err))
		}
	case 3:
		if _, _, err := instance.Confirm(Cli.GetTransactOpts(), username, passwd, big.NewInt(taskID), comment, status); err != nil {
			fmt.Println("failed to Confirm task3", err)
			return errors.New(fmt.Sprintf("failed to Confirm task3:%v", err))
		}
	case 4:
		status = 1
		if _, _, err := instance.Confirm(Cli.GetTransactOpts(), username, passwd, big.NewInt(taskID), comment, status); err != nil {
			fmt.Println("failed to Confirm task4", err)
			return errors.New(fmt.Sprintf("failed to Confirm task4:%v", err))
		}
	}
	return nil
}

func TaskList() (tasks []*TaskMsg, err error) {
	_issuers, err := instance.QryAllIssuers(Cli.GetCallOpts())
	if err != nil {
		fmt.Println("failed to QryAllIssuers", err)
		return nil, errors.New(fmt.Sprintf("failed to QryAllTasks:%v", err))
	}

	_works, err := instance.QryAllWorkers(Cli.GetCallOpts())
	if err != nil {
		fmt.Println("failed to QryAllIssuers", err)
		return nil, errors.New(fmt.Sprintf("failed to QryAllTasks:%v", err))
	}

	_bonus, err := instance.QryAllBonus(Cli.GetCallOpts())
	if err != nil {
		fmt.Println("failed to QryAllBonus", err)
		return nil, errors.New(fmt.Sprintf("failed to QryAllTasks:%v", err))
	}

	_comments, err := instance.QryAllComments(Cli.GetCallOpts())
	if err != nil {
		fmt.Println("failed to QryAllComments", err)
		return nil, errors.New(fmt.Sprintf("failed to QryAllTasks:%v", err))
	}

	_descs, err := instance.QryAllDescs(Cli.GetCallOpts())
	if err != nil {
		fmt.Println("failed to QryAllDescs", err)
		return nil, errors.New(fmt.Sprintf("failed to QryAllTasks:%v", err))
	}

	_status, err := instance.QryAllStatus(Cli.GetCallOpts())
	if err != nil {
		fmt.Println("failed to QryAllStatus", err)
		return nil, errors.New(fmt.Sprintf("failed to QryAllTasks:%v", err))
	}

	var task TaskMsg
	for k, _ := range _issuers {
		task.TaskID = fmt.Sprintf("%d", k)
		task.Bonus = _bonus[k].Int64()
		task.Comment = _comments[k]
		task.Desc = _descs[k]
		task.Issuer = _issuers[k]
		task.TaskStatus = _status[k]
		task.Worker = _works[k]
		tasks = append(tasks, &task)
	}
	return
}
